﻿using Common;
using Consul;
using ConsulEx;
using LogUtil;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace LYXAPI
{
    public static class ConsulHelper
    {
        /// <summary>
        /// 服务注册
        /// </summary>
        public static void ConsulRegister(this IConfiguration Configuration, IHostApplicationLifetime appLifeTime)
        {
            ConsulClient client = new ConsulClient(
                (ConsulClientConfiguration c) =>
                {
                    //c.Address = new Uri(Configuration["Consul:Address"]); //Consul服务中心地址
                    c.Address = new Uri(Configuration["Consul:consul_address"]);
                    c.Datacenter = Configuration["Consul:DataCenter"]; //指定数据中心，如果未提供，则默认为代理的数据中心。
                }
            );
            string checkUrl = Configuration["Consul:CheckUrl"];
            string ip = Configuration["ip"];
            string port = Configuration["port"];
            string serviceId = Guid.NewGuid().ToString();
            string serverName = Configuration["Consul:ServiceName"];
            //直接在VS里运行会报错，因为拿不到ip跟port，这些参数是启动的时候传入的，需要用指令启动
            //dotnet xxx.dll --urls="http://*:5005" --ip="127.0.0.1" --port=661
            client.Agent.ServiceRegister(new AgentServiceRegistration()
            {
                ID = serviceId, //服务编号，不可重复
                Name = serverName, //服务名称
                Port = int.Parse(port), //本程序的端口号
                Address = "127.0.0.1",//ip, //本程序的IP地址
                Check = new AgentServiceCheck()
                {
                    DeregisterCriticalServiceAfter = TimeSpan.FromMilliseconds(1), //服务停止后多久注销
                    Interval = TimeSpan.FromSeconds(5), //服务健康检查间隔
                    Timeout = TimeSpan.FromSeconds(5), //检查超时的时间
                    HTTP = $"http://{ip}:{port}{checkUrl}" //检查的地址
                }
            });

            Console.WriteLine($"{ip}:{port}");

            //var result = HttpUtil.GetResponse<List<ResServerCheck>>("http://192.168.132.131:8500/v1/health/checks/Test");
            ConsulKeepAlive(appLifeTime, client, ip, port, serviceId, serverName);

        }

        /// <summary>
        /// consul心跳保持(掉线自动重新注册)
        /// </summary>
        /// <param name="appLifeTime"></param>
        /// <param name="client"></param>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <param name="serviceId"></param>
        /// <param name="serverName"></param>
        private static void ConsulKeepAlive(IHostApplicationLifetime appLifeTime, ConsulClient client, string ip, string port, string serviceId, string serverName)
        {
            //从consul判断自身是否已经注册
            Task.Run(() =>
            {
                while (true)
                {
                    try
                    {
                        var isAlive = ServerUtil.Check(ip, port, serverName);
                        if (isAlive)
                        {
                            //睡眠一分钟
                            Thread.Sleep(1 * 60 * 1000);
                        }
                        else
                        {
                            appLifeTime.ApplicationStopped.Register(() =>
                            {
                                client.Agent.ServiceDeregister(serviceId);
                            });

                            Thread.Sleep(1 * 10 * 1000);
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.E(ex, "consul:注册失败");
                    }
                }
            });
        }
    }
}
